This document reproduces the different steps followed before generating the shiny app.
Including relevant libraries
library(tidyverse) # includes ggplot2 and readr
library(plotly) # interactive plots
Loading indices file
Mset <- read_delim(file="http://www3.mbari.org/science/upper-ocean-systems/biological-oceanography/GlobalModes/Mset.txt",comment="%",delim="\t")
Parsed with column specification:
cols(
YEAR = col_integer(),
MONTH = col_character(),
M1 = col_double(),
M2 = col_double(),
M3 = col_double(),
M4 = col_double(),
M5 = col_double(),
M6 = col_double()
)
Mset$time <- as.Date(paste(Mset$YEAR,Mset$MONTH,rep(15,length(Mset$YEAR))),format="%Y %m %d")
indices <- read_csv(file="http://www3.mbari.org/science/upper-ocean-systems/biological-oceanography/GlobalModes/climate_indices.csv",comment="%")
Parsed with column specification:
cols(
year = col_integer(),
month = col_integer(),
MEI = col_double(),
PDO = col_double(),
NPGO = col_double(),
EMI = col_double(),
Nino3 = col_double(),
Nino4 = col_double(),
AMO = col_double(),
NAO = col_double(),
ATL3 = col_double()
)
nb_time <- length(indices$year)
indices$time <- as.Date(paste(indices$year,indices$month,rep(15,nb_time)),format="%Y %m %d")
Plotting MEI & M1
plot(indices$time,indices$MEI,type="l",xlab="Time",ylab="Index")
points(Mset$time,Mset$M1,type="l",col="red")

Testing the use of varname & shading
indexname1 <- "PDO"
indexname2 <- "NPGO"
iok1 <- !is.na(indices[,indexname1])
ipos1 <- indices[,indexname1]>0 & !is.na(indices[,indexname1])
ineg1 <- indices[,indexname1]<0 & !is.na(indices[,indexname1])
x <- indices$time
y0 <- rep(0,nb_time)
plot(x,t(indices[,indexname1]),type="l",xlab="Time",ylab=indexname1)
polygon(c(x[iok1],rev(x[iok1])),c(y0[iok1],rev(t(indices[iok1,indexname1]))),col="skyblue")
points(x,t(indices[,indexname2]),type="l",col="red")

Testing 2 Y-axis
Based on https://www.r-bloggers.com/r-single-plot-with-two-different-y-axes/
indexname1 <- "M1"
indexname2 <- "MEI"
iok1 <- !is.na(Mset[,indexname1])
x <- Mset$time
y0 <- rep(0,length(Mset$YEAR))
par(mar = c(5,5,2,5))
plot(x,t(Mset[,indexname1]),type="l",xlab="Time",ylab=indexname1)
par(new=T)
with(indices,plot(time,MEI,type="l",axes=F,xlab=NA,ylab=NA,col="red",pch=16,cex=1.2))
#plot(indices$time,t(indices[,indexname2]),type="l",axes=F,xlab=NA, ylab=NA,col="red")
axis(side = 4, col="red")
mtext(side = 4, line = 3, indexname2,col="red")
legend("topleft",legend=c(indexname1,indexname2),lty=c(1,1),col=c("black", "red"))

Testing ggplot2 - area plot, double axis, interactive plot
indexname1 <- "M3"
indexname2 <- "PDO"
max1 <- max(Mset[,indexname1],na.rm=TRUE)
max2 <- max(indices[,indexname2],na.rm=TRUE)
Mset[,"varpos"] <- Mset[,indexname1]
Mset[,"varneg"] <- Mset[,indexname1]
Mset$varpos[which(Mset$varpos > 0)] <- rep(0, length(which(Mset$varpos > 0)))
Mset$varneg[which(Mset$varneg < 0)] <- rep(0, length(which(Mset$varneg < 0)))
commonxM <- Mset$time %in% indices$time
commonxI <- indices$time %in% Mset$time
subsetM <- Mset[commonxM,indexname1]
subsetI <- indices[commonxI,indexname2]
iok1 <- !is.na(subsetM) & !is.na(subsetI)
r=cor(subsetM[iok1,],subsetI[iok1,])
legname <- paste(indexname2," (r = ",toString(floor(r*100)/100),")",sep="")
p <- ggplot() +
geom_area(data = Mset, aes(x=time, y=varpos), fill="blue") +
geom_area(data = Mset, aes(x=time, y=varneg), fill="red") +
geom_line(data = indices, aes(x=time, y=eval(as.name(indexname2))/(max2/max1), color=legname),size=0.5) +
scale_y_continuous(sec.axis = sec_axis(trans = ~.*(max2/max1),name = indexname2)) +
scale_x_date(limits = c(min(Mset$time),max(Mset$time)),expand=c(0,0)) +
labs(x ="Time", y = indexname1) +
theme(legend.position=c(0.15, 0.95),legend.key.width=unit(3,"line"),legend.background = element_rect(fill="transparent"),
legend.text=element_text(size=11)) +
scale_colour_manual("",
breaks = c(legname),
values = c("black"))
p2=plotly_build(p)
style(p2) %>% layout( legend = list(x = 0.01, y = 1) ) # needed because ggplotly removes the legend position
LS0tCnRpdGxlOiAiQ2xpbWF0ZSBJbmRpY2VzIE5vdGVib29rIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdAogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKLS0tCgpUaGlzIGRvY3VtZW50IHJlcHJvZHVjZXMgdGhlIGRpZmZlcmVudCBzdGVwcyBmb2xsb3dlZCBiZWZvcmUgZ2VuZXJhdGluZyB0aGUgc2hpbnkgYXBwLgoKIyNJbmNsdWRpbmcgcmVsZXZhbnQgbGlicmFyaWVzCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpICAjIGluY2x1ZGVzIGdncGxvdDIgYW5kIHJlYWRyCmxpYnJhcnkocGxvdGx5KSAgICAgIyBpbnRlcmFjdGl2ZSBwbG90cwpgYGAKCiMjTG9hZGluZyBpbmRpY2VzIGZpbGUKYGBge3J9Ck1zZXQgPC0gcmVhZF9kZWxpbShmaWxlPSJodHRwOi8vd3d3My5tYmFyaS5vcmcvc2NpZW5jZS91cHBlci1vY2Vhbi1zeXN0ZW1zL2Jpb2xvZ2ljYWwtb2NlYW5vZ3JhcGh5L0dsb2JhbE1vZGVzL01zZXQudHh0Iixjb21tZW50PSIlIixkZWxpbT0iXHQiKQpNc2V0JHRpbWUgPC0gYXMuRGF0ZShwYXN0ZShNc2V0JFlFQVIsTXNldCRNT05USCxyZXAoMTUsbGVuZ3RoKE1zZXQkWUVBUikpKSxmb3JtYXQ9IiVZICVtICVkIikKaW5kaWNlcyA8LSByZWFkX2NzdihmaWxlPSJodHRwOi8vd3d3My5tYmFyaS5vcmcvc2NpZW5jZS91cHBlci1vY2Vhbi1zeXN0ZW1zL2Jpb2xvZ2ljYWwtb2NlYW5vZ3JhcGh5L0dsb2JhbE1vZGVzL2NsaW1hdGVfaW5kaWNlcy5jc3YiLGNvbW1lbnQ9IiUiKQpuYl90aW1lIDwtIGxlbmd0aChpbmRpY2VzJHllYXIpCmluZGljZXMkdGltZSA8LSBhcy5EYXRlKHBhc3RlKGluZGljZXMkeWVhcixpbmRpY2VzJG1vbnRoLHJlcCgxNSxuYl90aW1lKSksZm9ybWF0PSIlWSAlbSAlZCIpCmBgYAoKCiMjUGxvdHRpbmcgTUVJICYgTTEKCmBgYHtyfQpwbG90KGluZGljZXMkdGltZSxpbmRpY2VzJE1FSSx0eXBlPSJsIix4bGFiPSJUaW1lIix5bGFiPSJJbmRleCIpCnBvaW50cyhNc2V0JHRpbWUsTXNldCRNMSx0eXBlPSJsIixjb2w9InJlZCIpCmBgYAoKCiMjIFRlc3RpbmcgdGhlIHVzZSBvZiB2YXJuYW1lICYgc2hhZGluZwoKYGBge3J9CmluZGV4bmFtZTEgPC0gIlBETyIKaW5kZXhuYW1lMiA8LSAiTlBHTyIKaW9rMSA8LSAhaXMubmEoaW5kaWNlc1ssaW5kZXhuYW1lMV0pCmlwb3MxIDwtIGluZGljZXNbLGluZGV4bmFtZTFdPjAgJiAhaXMubmEoaW5kaWNlc1ssaW5kZXhuYW1lMV0pCmluZWcxIDwtIGluZGljZXNbLGluZGV4bmFtZTFdPDAgJiAhaXMubmEoaW5kaWNlc1ssaW5kZXhuYW1lMV0pCnggPC0gaW5kaWNlcyR0aW1lCnkwIDwtIHJlcCgwLG5iX3RpbWUpCnBsb3QoeCx0KGluZGljZXNbLGluZGV4bmFtZTFdKSx0eXBlPSJsIix4bGFiPSJUaW1lIix5bGFiPWluZGV4bmFtZTEpCnBvbHlnb24oYyh4W2lvazFdLHJldih4W2lvazFdKSksYyh5MFtpb2sxXSxyZXYodChpbmRpY2VzW2lvazEsaW5kZXhuYW1lMV0pKSksY29sPSJza3libHVlIikKcG9pbnRzKHgsdChpbmRpY2VzWyxpbmRleG5hbWUyXSksdHlwZT0ibCIsY29sPSJyZWQiKQpgYGAKCiMjIFRlc3RpbmcgMiBZLWF4aXMKCkJhc2VkIG9uIGh0dHBzOi8vd3d3LnItYmxvZ2dlcnMuY29tL3Itc2luZ2xlLXBsb3Qtd2l0aC10d28tZGlmZmVyZW50LXktYXhlcy8gCgpgYGB7cn0KaW5kZXhuYW1lMSA8LSAiTTEiCmluZGV4bmFtZTIgPC0gIk1FSSIKaW9rMSA8LSAhaXMubmEoTXNldFssaW5kZXhuYW1lMV0pCnggPC0gTXNldCR0aW1lCnkwIDwtIHJlcCgwLGxlbmd0aChNc2V0JFlFQVIpKQpwYXIobWFyID0gYyg1LDUsMiw1KSkKcGxvdCh4LHQoTXNldFssaW5kZXhuYW1lMV0pLHR5cGU9ImwiLHhsYWI9IlRpbWUiLHlsYWI9aW5kZXhuYW1lMSkKcGFyKG5ldz1UKQp3aXRoKGluZGljZXMscGxvdCh0aW1lLE1FSSx0eXBlPSJsIixheGVzPUYseGxhYj1OQSx5bGFiPU5BLGNvbD0icmVkIixwY2g9MTYsY2V4PTEuMikpCiNwbG90KGluZGljZXMkdGltZSx0KGluZGljZXNbLGluZGV4bmFtZTJdKSx0eXBlPSJsIixheGVzPUYseGxhYj1OQSwgeWxhYj1OQSxjb2w9InJlZCIpCmF4aXMoc2lkZSA9IDQsIGNvbD0icmVkIikKbXRleHQoc2lkZSA9IDQsIGxpbmUgPSAzLCBpbmRleG5hbWUyLGNvbD0icmVkIikKbGVnZW5kKCJ0b3BsZWZ0IixsZWdlbmQ9YyhpbmRleG5hbWUxLGluZGV4bmFtZTIpLGx0eT1jKDEsMSksY29sPWMoImJsYWNrIiwgInJlZCIpKQpgYGAKCiMjIFRlc3RpbmcgZ2dwbG90MiAtIGFyZWEgcGxvdCwgZG91YmxlIGF4aXMsIGludGVyYWN0aXZlIHBsb3QKCmBgYHtyfQppbmRleG5hbWUxIDwtICJNMyIKaW5kZXhuYW1lMiA8LSAiUERPIgptYXgxIDwtIG1heChNc2V0WyxpbmRleG5hbWUxXSxuYS5ybT1UUlVFKQptYXgyIDwtIG1heChpbmRpY2VzWyxpbmRleG5hbWUyXSxuYS5ybT1UUlVFKQpNc2V0WywidmFycG9zIl0gPC0gTXNldFssaW5kZXhuYW1lMV0KTXNldFssInZhcm5lZyJdIDwtIE1zZXRbLGluZGV4bmFtZTFdCgpNc2V0JHZhcnBvc1t3aGljaChNc2V0JHZhcnBvcyA+IDApXSA8LSByZXAoMCwgbGVuZ3RoKHdoaWNoKE1zZXQkdmFycG9zID4gMCkpKQpNc2V0JHZhcm5lZ1t3aGljaChNc2V0JHZhcm5lZyA8IDApXSA8LSByZXAoMCwgbGVuZ3RoKHdoaWNoKE1zZXQkdmFybmVnIDwgMCkpKQoKY29tbW9ueE0gPC0gTXNldCR0aW1lICVpbiUgaW5kaWNlcyR0aW1lCmNvbW1vbnhJIDwtIGluZGljZXMkdGltZSAlaW4lIE1zZXQkdGltZQpzdWJzZXRNIDwtIE1zZXRbY29tbW9ueE0saW5kZXhuYW1lMV0Kc3Vic2V0SSA8LSBpbmRpY2VzW2NvbW1vbnhJLGluZGV4bmFtZTJdCmlvazEgPC0gIWlzLm5hKHN1YnNldE0pICYgIWlzLm5hKHN1YnNldEkpCnI9Y29yKHN1YnNldE1baW9rMSxdLHN1YnNldElbaW9rMSxdKQpsZWduYW1lIDwtIHBhc3RlKGluZGV4bmFtZTIsIiAociA9ICIsdG9TdHJpbmcoZmxvb3IocioxMDApLzEwMCksIikiLHNlcD0iIikKCnAgPC0gZ2dwbG90KCkgKwogIGdlb21fYXJlYShkYXRhID0gTXNldCwgYWVzKHg9dGltZSwgeT12YXJwb3MpLCBmaWxsPSJibHVlIikgKwogIGdlb21fYXJlYShkYXRhID0gTXNldCwgYWVzKHg9dGltZSwgeT12YXJuZWcpLCBmaWxsPSJyZWQiKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBpbmRpY2VzLCBhZXMoeD10aW1lLCB5PWV2YWwoYXMubmFtZShpbmRleG5hbWUyKSkvKG1heDIvbWF4MSksIGNvbG9yPWxlZ25hbWUpLHNpemU9MC41KSArCiAgc2NhbGVfeV9jb250aW51b3VzKHNlYy5heGlzID0gc2VjX2F4aXModHJhbnMgPSB+LioobWF4Mi9tYXgxKSxuYW1lID0gaW5kZXhuYW1lMikpICsKICBzY2FsZV94X2RhdGUobGltaXRzID0gYyhtaW4oTXNldCR0aW1lKSxtYXgoTXNldCR0aW1lKSksZXhwYW5kPWMoMCwwKSkgKwogIGxhYnMoeCAgPSJUaW1lIiwgeSA9IGluZGV4bmFtZTEpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249YygwLjE1LCAwLjk1KSxsZWdlbmQua2V5LndpZHRoPXVuaXQoMywibGluZSIpLGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGw9InRyYW5zcGFyZW50IiksCiAgICAgICAgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTEpKSArCiAgc2NhbGVfY29sb3VyX21hbnVhbCgiIiwgCiAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBjKGxlZ25hbWUpLAogICAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gYygiYmxhY2siKSkKcDI9cGxvdGx5X2J1aWxkKHApICAgCnN0eWxlKHAyKSAlPiUgbGF5b3V0KCBsZWdlbmQgPSBsaXN0KHggPSAwLjAxLCB5ID0gMSkgKSAgICMgbmVlZGVkIGJlY2F1c2UgZ2dwbG90bHkgcmVtb3ZlcyB0aGUgbGVnZW5kIHBvc2l0aW9uCmBgYAoKCg==